package com.itlong.cloud.network.tcp.mina;

import com.itlong.cloud.network.tcp.mina.server.ServerCodeFactory;
import com.itlong.cloud.network.tcp.mina.server.ServerHandler;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.filter.logging.MdcInjectionFilter;
import org.apache.mina.integration.spring.InetSocketAddressEditor;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.springframework.beans.factory.config.CustomEditorConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

import java.beans.PropertyEditor;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.HashMap;
import java.util.Map;

/**
* <desc>
*      mina初始化
* </desc>
*
* @createDate 2017/10/26
*/
@Configuration
public class SerialServerConfig {

    private static final Logger LOG = LoggerFactory.getLogger(SerialServerConfig.class);


    /**
     * <desc>
     *      日志过滤器记录所有的事件和请求
     * </desc>
     *
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/26
     */
    @Bean
    public LoggingFilter loggingFilter() {
        return new LoggingFilter();
    }

    /**
     * <desc>
     *      编码解码过滤器
     * </desc>
     *
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/26
     */
    @Bean
    public ServerCodeFactory serverCodeFactory() {
        return new ServerCodeFactory();
    }

    /**
     * <desc>
     *      在多描述编码(MDC，Multiple Description Coding)中注入IoSession的key属性
     * </desc>
     *
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/26
     */
    @Bean
    public MdcInjectionFilter mdcInjectionFilter(){
        return new MdcInjectionFilter(MdcInjectionFilter.MdcKey.remoteAddress);
    }

    /**
     * <desc>
     *      流处理
     * </desc>
     *
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/25
     */
    @Bean
    public IoHandlerAdapter ioHandlerAdapter() {
        return new ServerHandler();
    }

    /**
     * <desc>
     *      executorFilter多线程处理
     * </desc>
     *
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/25
     */
    @Bean
    public ExecutorFilter executorFilter(){
        return new ExecutorFilter();
    }

    /**
     * <desc>
     *      此部分被 NioSocketAcceptor 隐式使用，无此则会报字符串无法转换成 InetSocketAddress
     * </desc>
     *
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/26
     */
    @Bean
    public CustomEditorConfigurer customEditorConfigurer(){
        CustomEditorConfigurer customEditorConfigurer=new CustomEditorConfigurer();
        Map<Class<?>, Class<? extends PropertyEditor >> map= new HashMap<>();
        map.put(SocketAddress.class,InetSocketAddressEditor.class);
        customEditorConfigurer.setCustomEditors(map);
        return customEditorConfigurer;
    }

    /**
     * <desc>
     *      设置端口号
     * </desc>
     *
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/26
     */
    @Bean
    public InetSocketAddress inetSocketAddress(){
        return new InetSocketAddress(9999);
    }

    /**
     * <desc>
     *      配置ioAcceptor
     * </desc>
     *
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/26
     */
    @Bean(initMethod = "bind",destroyMethod = "unbind")
    @Lazy(false)
    public SocketAcceptor ioAcceptor()
    {
        //创建socket接收器
        SocketAcceptor acceptor=new NioSocketAcceptor();
        //绑定处理handler
        acceptor.setHandler(ioHandlerAdapter());
        acceptor.setReuseAddress(true);
        //设置过滤器
        acceptor.getFilterChain().addLast("loggingFilter",loggingFilter());
        acceptor.getFilterChain().addLast("codecFilter",
                new ProtocolCodecFilter(serverCodeFactory()));
        acceptor.getFilterChain().addLast("executor",executorFilter());
        acceptor.getFilterChain().addLast("mdcInjectionFilter",mdcInjectionFilter());
        acceptor.setDefaultLocalAddress(inetSocketAddress());
        acceptor.setHandler(ioHandlerAdapter());
        return acceptor;
    }

}